#include "app_device.h"
#include "app_bt.h"

static device_t *device = NULL;
#define DEVICE_BUFFER_SIZE 1024
#define DEVICE_POOL_SIZE 5
#define WRITE_INTERVAL_MS 200

static int send_task_func(void *arg){
    char buffer[128];
    //从缓冲区读取数据
    int len = app_buffer_read(device->up_buffer, buffer, sizeof(buffer));
    char *json =app_message_charstoJSON(buffer, len);
    int result = app_mqtt_send(json);
    log_debug("send data to mqtt");
    //将数据发送到mqtt
    if (result != 0)
    {
        log_debug("send data to mqtt failed");
        return -1;
    }
    log_debug("send data to mqtt success");
    return 0;
}

/**
 * @brief 读取线程函数
 * 
 * @param arg 
 * @return void* 
 */
static void *read_thread_func(void *arg){
    while (device->is_running)
    {
        //读取数据
        char buffer[128];
        int len =read(device->fd, buffer, sizeof(buffer));
        if (len > 0)
        {
                    //判断是否读取成功
        if (device->post_read != NULL)
        {
            //将读取到到蓝牙数据转换为字符数组
            len = device->post_read(buffer, len);
            if (len > 0){
            //将读取到的数据写入缓冲区
            app_buffer_write(device->up_buffer, buffer, len);
            //通过线程池执行发送写入的数据
            app_pool_registerTask(send_task_func,NULL);
            }
        }
        }
        

    }
    
}

/**
 * @brief 设备初始化
 * 
 * @param filename 
 * @return int 
 */
device_t *app_device_init(char *filename){
    if (device != NULL)
    {
        return device;
    }
    device = (device_t *)malloc(sizeof(device_t));
    device->filename = filename;
    device->fd = open(filename, O_RDWR);
    device->is_running = 0;
    device->last_write_time = 0;
    device->down_buffer = app_buffer_init(DEVICE_BUFFER_SIZE);
    device->up_buffer = app_buffer_init(DEVICE_BUFFER_SIZE);
    device->post_read = NULL;
    device->pre_write = NULL;

    app_pool_init(DEVICE_POOL_SIZE);
    app_mqtt_init();
    return device;
}

int write_thread_func(void *arg){
    char buffer[128];

    //从缓冲区读取数据
    int len = app_buffer_read(device->down_buffer,buffer, sizeof(buffer));
    if (len > 0 && device->pre_write != NULL)
    {
        int interval = 0;
        //将字符数组转换为蓝牙数据
        len = device->pre_write(buffer, len);
        while((interval = (app_common_getCurrentTime() - device->last_write_time)) < WRITE_INTERVAL_MS)
        {
            device->last_write_time = app_common_getCurrentTime();
            usleep(WRITE_INTERVAL_MS - interval);
        }
        device->last_write_time = app_common_getCurrentTime();
     
        int writelen = write(device->fd, buffer, len);
        if (len != writelen){
            log_debug("write data to device failed");
            return -1;
        }
        
        log_debug("write data to device success %s",app_common_charsToHex(buffer, writelen));
        
    }
    
}

static int receive_msg_callback(char *json){
    char buffer[128];
    //将json转换为字符数组
    int len = app_message_jsonToChars(json,buffer,sizeof(buffer));
    if (len > 0){
        //将字符数组写入缓冲区
        app_buffer_write(device->down_buffer, buffer, len);
        //通过线程池执行发送写入的数据
        app_pool_registerTask(write_thread_func,NULL);
    }
}

/**
 * @brief 启动设备
 * 
 * @return int 
 */
int app_device_start(void){
    if (device->is_running == 1)
    {
        log_debug("device is running");
        return 0;
    }
    device->is_running = 1;
    log_debug("device start");
    int result = pthread_create(&device->read_thread, NULL, read_thread_func, NULL);
    if (result != 0)
    {
        log_debug("create read thread failed");
        return -1;
    }

    //注册mqtt回调函数
    app_mqtt_registerRecvCallback(receive_msg_callback);
    return 0;
}

/**
 * @brief 销毁设备
 * 
 * @return int 
 */
int app_device_destroy(void){
    device->is_running = 0;
    pthread_cancel(device->read_thread);
    device->filename = NULL;
    close(device->fd);
    device->post_read = NULL;
    device->pre_write = NULL;
    device->last_write_time = 0;
    app_buffer_free(device->down_buffer);
    app_buffer_free(device->up_buffer);
    free(device);
    app_pool_close();
    app_mqtt_close();
    return 0;
}
